package com.neusoft.aclome.cmp.cloud.server.jcce.service;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.neusoft.aclome.cmp.cloud.api.request.vm.VmRequest;
import com.neusoft.aclome.cmp.cloud.server.jcce.dto.request.ConsultProcessRequest;
import com.neusoft.aclome.cmp.cloud.server.jcce.dto.response.ConsultProcessDTO;
import com.neusoft.aclome.cmp.cloud.server.jcce.dto.response.Overview2DTO;
import com.neusoft.aclome.cmp.cloud.server.jcce.entity.ConsultProcessEntity;
import com.neusoft.aclome.cmp.cloud.server.jcce.repository.ConsultProcessMapper;
import com.neusoft.aclome.cmp.cloud.server.model.entity.DataCenterEntity;
import com.neusoft.aclome.cmp.cloud.server.model.entity.VirtualMachineEntity;
import com.neusoft.aclome.cmp.cloud.server.pub.cloud.entity.CloudPlatformEntity;
import com.neusoft.aclome.cmp.cloud.server.pub.cloud.repository.CloudPlatformMapper;
import com.neusoft.aclome.cmp.cloud.server.pub.cloud.service.PubVirtualMachineService;
import com.neusoft.aclome.cmp.cloud.server.repository.database.mapper.DataCenterMapper;
import com.neusoft.aclome.cmp.cloud.server.service.OrganizationService;
import com.neusoft.aclome.cmp.cloud.server.service.VirtualMachineService;
import com.neusoft.aclome.cmp.common.constants.AclomeCmpOrganizationType;
import com.neusoft.aclome.cmp.organization.api.model.vo.ResourcePoolVO;
import com.neusoft.pub.cloud.provider.entity.VirtualMachine;
import com.neusoft.pub.cloud.provider.request.ListVirtualMachineRequest;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * describe :
 *
 * @author hao.dd
 * @date 2024/4/12
 */
@Service
public class ConsultProcessService {

    private static final Logger log = LoggerFactory.getLogger(ConsultProcessService.class);

    @Autowired
    private PubVirtualMachineService pubVirtualMachineService;

    @Autowired
    private VirtualMachineService privateVirtualMachineService;

    @Autowired
    private ConsultProcessMapper consultProcessMapper;

    @Autowired
    private OrganizationService organizationService;

    @Autowired
    private CloudPlatformMapper cloudPlatformMapper;

    @Autowired
    private DataCenterMapper dataCenterMapper;

    // 查询磋商任务逻辑，要计算时间和百分比
    public List<ConsultProcessDTO> getConsultationProcessNew() {
        List<ResourcePoolVO> privateDataCenters = organizationService.listResourcePoolByType(AclomeCmpOrganizationType.DATA_CENTER).getData();
//        dataCenterService.listDataCenter(false,false,false);
        List<DataCenterEntity> dataCenterEntities = dataCenterMapper.listDataCenter();
        Map<Integer, String> privateIdNameMap = dataCenterEntities.stream().collect(Collectors.toMap(x -> x.getId(), x -> x.getName()));
        // 收集公有云id映射map
        Map<Integer, ResourcePoolVO> privateIdMap = privateDataCenters.stream().collect(Collectors.toMap(x -> x.getDataCenterId(), Function.identity(), (u, v) -> v, HashMap::new));

        List<CloudPlatformEntity> allPubPlat = cloudPlatformMapper.selectAll();
        Map<Integer, CloudPlatformEntity> pubIdMap = allPubPlat.stream().collect(Collectors.toMap(x -> x.getId(), Function.identity()));

        // 排序
        Example example = new Example(ConsultProcessEntity.class);
        example.setOrderByClause("start_time desc");

        PageHelper.startPage(1, 20);
        List<ConsultProcessEntity> entityList = consultProcessMapper.selectByExample(example);
        // entityList = (entityList.size() <= 20) ? entityList : entityList.subList(0, 20);

        // TODO 需要补上配额和已用
        setConsultProcessPropertis(entityList);

        List<ConsultProcessDTO> result = entityList.stream().map(x -> {
            ConsultProcessDTO consultProcessDTO = new ConsultProcessDTO();
            BeanUtils.copyProperties(x, consultProcessDTO);
            setGraphInfo(x, consultProcessDTO);
            setConsultInfos(privateIdMap, pubIdMap, privateIdNameMap, x, consultProcessDTO);
            return consultProcessDTO;
        }).collect(Collectors.toList());
        return result;
    }

    private void setConsultProcessPropertis(List<ConsultProcessEntity> entityList) {
        for (ConsultProcessEntity e : entityList) {
            // 四个步骤
            if (e.getEndTime() == null) {
                // 600秒一条 一共2400
                Long second = (System.currentTimeMillis() - e.getStartTime().getTime()) / 1000;
                log.info("second:" + second);
                if (second < 600) {
                    e.setProfitDistribution(Float.valueOf(second * 100f / 600).intValue());
                    e.setResourcePricing(0);
                    e.setCloudFeedback(0);
                    e.setMonitoringGovernance(0);
                }
                if (second >= 600 && second < 1200) {
                    e.setProfitDistribution(100);
                    e.setCloudFeedback(Float.valueOf((600 - (1200 - second)) * 100f / 600).intValue());
                    e.setCloudFeedback(0);
                    e.setMonitoringGovernance(0);
                }
                if (second >= 1200 && second < 1800) {
                    e.setProfitDistribution(100);
                    e.setResourcePricing(100);
                    e.setCloudFeedback(Float.valueOf((600 - (1800 - second)) * 100f / 600).intValue());
                    e.setMonitoringGovernance(0);
                }
                if (second >= 1800 && second < 2400) {
                    e.setProfitDistribution(100);
                    e.setResourcePricing(100);
                    e.setCloudFeedback(100);
                    e.setCloudFeedback(Float.valueOf((600 - (2400 - second)) * 100f / 600).intValue());
                }
                if (second >= 2400) {
                    // 大于2400 置为完成，结束时间随机
                    e.setProfitDistribution(100);
                    e.setResourcePricing(100);
                    e.setCloudFeedback(100);
                    e.setMonitoringGovernance(100);
                    // 设置结束时间
                    Random rand = new Random();
                    int max = second.intValue() > 7200 ? 7200 : second.intValue();
                    int randomNum = 2400 + rand.nextInt(max - 2400);
                    e.setEndTime(new Date(e.getStartTime().getTime() + (randomNum * 1000)));
                }
                e.setPercentage(new BigDecimal((e.getProfitDistribution() + e.getResourcePricing() + e.getCloudFeedback() + e.getMonitoringGovernance()) / 400f * 100));
            }

            try {
                consultProcessMapper.updateByPrimaryKey(e);
            } catch (Exception ee) {
                ee.printStackTrace();
            }
        }
    }

    private void setConsultInfos(Map<Integer, ResourcePoolVO> privateIdMap, Map<Integer, CloudPlatformEntity> pubIdMap,
                                 Map<Integer, String> privateIdNameMap, ConsultProcessEntity x, ConsultProcessDTO consultProcessDTO) {
        // 通过虚拟机查询已用配额
        // 公私有云虚拟机
        ListVirtualMachineRequest pubReq = new ListVirtualMachineRequest();
        pubReq.setPageNumber(1);
        pubReq.setPageSize(1000);
        List<VirtualMachine> pubVMs = pubVirtualMachineService.listLocalInstance(pubReq).getPageData();

        // 私有云虚拟机
        List<VirtualMachineEntity> privateVMs = new ArrayList<>();
        try {
            privateVMs.addAll(privateVirtualMachineService.listVMs(new VmRequest()));
        } catch (Exception e) {
            e.printStackTrace();
        }

        String pubCloudIds = x.getPubCloudIds();
        String privCloudIds = x.getPrivCloudIds();

        if (StringUtils.isNotBlank(pubCloudIds)) {
            consultProcessDTO.setConsultInfos(Arrays.stream(pubCloudIds.split(",")).map(pubCloudId -> {
                CloudPlatformEntity cloudPlatformEntity = pubIdMap.get(Integer.valueOf(pubCloudId));

                ConsultProcessDTO.ConsultInfo consultInfo = new ConsultProcessDTO.ConsultInfo();
                if(cloudPlatformEntity!=null){
                    consultInfo.setId(cloudPlatformEntity.getId());
                    consultInfo.setType("public");
                    consultInfo.setName(cloudPlatformEntity.getPlatformName());
                    consultInfo.setCpuQuota(cloudPlatformEntity.getCpuQuota());
                    consultInfo.setMemoryQuota(cloudPlatformEntity.getMemQuota());
                    consultInfo.setCapacityQuota(cloudPlatformEntity.getCapacityQuota());
                    consultInfo.setBandwidthQuota(cloudPlatformEntity.getBandwidthQuota());
                    // 增加已用
                    // 过滤出本云商的虚拟机
                    List<VirtualMachine> vmList = pubVMs.stream().filter(vm -> cloudPlatformEntity.getId().equals(vm.getDataCenterId())).collect(Collectors.toList());
                    // 通过虚拟机查已用配额
                    Integer cpuValue = vmList.stream().mapToInt(vm -> vm.getCpu()).sum();
                    Integer memValue = vmList.stream().mapToInt(vm -> vm.getMemory()).sum() / 1024;
                    // TODO 目前虚拟机表没保存存储 暂时替代
                    Integer storageValue = new Double(((double) cpuValue / (double) cloudPlatformEntity.getCpuQuota()) * cloudPlatformEntity.getCapacityQuota()).intValue();
                    consultInfo.setCpuUsed(cpuValue);
                    consultInfo.setMemoryUsed(memValue);
                    consultInfo.setCapacityUsed(storageValue);
                }

                return consultInfo;
            }).collect(Collectors.toList()));
        }

        if (StringUtils.isNotBlank(privCloudIds)) {
            List<ConsultProcessDTO.ConsultInfo> infos = consultProcessDTO.getConsultInfos() == null ? new ArrayList<>() : consultProcessDTO.getConsultInfos();
            infos.addAll(Arrays.stream(privCloudIds.split(",")).map(privateCloudId -> {
                ResourcePoolVO resourcePoolVO = privateIdMap.get(Integer.valueOf(privateCloudId));
                ConsultProcessDTO.ConsultInfo consultInfo = new ConsultProcessDTO.ConsultInfo();
                if(resourcePoolVO != null){
                    consultInfo.setCpuQuota(resourcePoolVO.getVcpus());
                    double v = new BigDecimal(resourcePoolVO.getMem()).divide(BigDecimal.valueOf(1073741824), 0, RoundingMode.DOWN).doubleValue();
                    consultInfo.setMemoryQuota((int) v);
                    double v2 = new BigDecimal(resourcePoolVO.getStorage()).divide(BigDecimal.valueOf(1073741824), 0, RoundingMode.DOWN).doubleValue();
                    consultInfo.setCapacityQuota((int) v2);
                    consultInfo.setId(resourcePoolVO.getId());
                    consultInfo.setType("private");
                    consultInfo.setName(privateIdNameMap.get(Integer.valueOf(privateCloudId)));
                    // 过滤出本云商的虚拟机
                    List<VirtualMachineEntity> vmList = privateVMs.stream().filter(vm -> resourcePoolVO.getDataCenterId().equals(vm.getResourceDataCenterId())).collect(Collectors.toList());
                    Long cpuValue = vmList.stream().mapToLong(vm -> vm.getCpu()).sum();
                    Long memValue = vmList.stream().mapToLong(vm -> vm.getMemory()).sum() / 1024 / 1024 / 1024;
                    Long storageValue = vmList.stream().mapToLong(vm -> vm.getDisk()).sum() / 1024 / 1024 / 1024;
                    consultInfo.setCpuUsed(cpuValue.intValue());
                    consultInfo.setMemoryUsed(memValue.intValue());
                    consultInfo.setCapacityUsed(storageValue.intValue());
                }
                return consultInfo;
            }).collect(Collectors.toList()));
        }
    }

    private static void setGraphInfo(ConsultProcessEntity x, ConsultProcessDTO consultProcessDTO) {
        ArrayList<ConsultProcessDTO.GraphInfo> graphInfos = new ArrayList<>();
        ConsultProcessDTO.GraphInfo graphInfo1 = new ConsultProcessDTO.GraphInfo();
        graphInfo1.setId(1);
        graphInfo1.setName("收益分配");
        graphInfo1.setValue(x.getProfitDistribution());
        graphInfos.add(graphInfo1);

        ConsultProcessDTO.GraphInfo graphInfo2 = new ConsultProcessDTO.GraphInfo();
        graphInfo2.setId(2);
        graphInfo2.setName("资源定价");
        graphInfo2.setValue(x.getResourcePricing());
        graphInfos.add(graphInfo2);

        ConsultProcessDTO.GraphInfo graphInfo3 = new ConsultProcessDTO.GraphInfo();
        graphInfo3.setId(3);
        graphInfo3.setName("云商反馈");
        graphInfo3.setValue(x.getCloudFeedback());
        graphInfos.add(graphInfo3);

        ConsultProcessDTO.GraphInfo graphInfo4 = new ConsultProcessDTO.GraphInfo();
        graphInfo4.setId(4);
        graphInfo4.setName("监控治理");
        graphInfo4.setValue(x.getMonitoringGovernance());
        graphInfos.add(graphInfo4);

        consultProcessDTO.setGraphInfos(graphInfos);
    }

    // 创建磋商任务
    public void saveConsultationProcess(ConsultProcessRequest consultProcessRequest) {
        ConsultProcessEntity consultProcessEntity = new ConsultProcessEntity();
        BeanUtils.copyProperties(consultProcessRequest, consultProcessEntity);
        consultProcessEntity.setStartTime(new Date());
        consultProcessMapper.insert(consultProcessEntity);
    }
}
